#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>


#include "packets/packet.h"
#include "packets/CRC.h"

#include "communication/input.h"
#include "communication/comPort.h"
#include "features/adc/adc.h"
#include "board/board.h"

#include "packets/structs/msgHeaderDefs.h"
#include "packets/structs/encPacketStructs.h"
#include "packets/structs/adcPacketStructs.h"

#include "extFlash/flash.h"

#include "features/dio/dio.h"
#include "features/dac/dac.h"


#include "test/test.h"


//#define spoof

volatile uint8_t USB_data[9];
volatile flashAdcData_t adcBulkPacket;

uint8_t testPacket[12] = {0x55,1,2,3,4,5,6,7,8,9,0,0};


uint16_t i,timeoutInc;
int main (void)
{	
	brdInit();					//setup of any board specific items		
	sei();

	_delay_ms(1);

	sendDaqReady();

	while (1) 
	{	
		
		switch(daqAlloc.standAlone.aqState)
		{
			case AQ_UKNOWN_STATE:
					
				if (dataInBuf(&bufRxD1))
				{
					if(comPortGet((uint8_t *)USB_data))globalMsgHandler((uint8_t *)USB_data);
				}
				
			break;
			case AQ_INIT_STATE:
				
				if (dataInBuf(&bufRxD1))
				{
					if(comPortGet((uint8_t *)USB_data))globalMsgHandler((uint8_t *)USB_data);
				}
				
			break;
			case AQ_AQUIRE_STATE:
				
				if(flash.curAddr >= flash.finAddr)
				{
					flashDeSel();
					daqAlloc.standAlone.aqState = AQ_SEND_STATE;
					TCC0.INTCTRLA &= ~TC0_OVFINTLVL_gm;	
					flash.curAddr = 0;
		
					ADCA.CH0.INTCTRL = ADC_CH_INTLVL_OFF_gc;
					ADCA.CH1.INTCTRL = ADC_CH_INTLVL_OFF_gc;
					ADCA.CH2.INTCTRL = ADC_CH_INTLVL_OFF_gc;
					ADCA.CH3.INTCTRL = ADC_CH_INTLVL_OFF_gc;
				}
				else if (dataInBuf(&bufRxD1))
				{
					if(comPortGet((uint8_t *)USB_data))globalMsgHandler((uint8_t *)USB_data);
				}
				
			break;
			case AQ_SEND_STATE:
			
			
		
			for(i=0;i<flash.numChannels;i++)
			{
				//zero the current external memory Address
				flash.curAddr = 0;
				
				//send info packet
				flashAdcInfo(i);
				while(dataInBuf(&bufTxD1));
				asm("nop");
#ifndef spoof		
				while(daqAlloc.standAlone.recInfoAck == 0)
				{
					if (dataInBuf(&bufRxD1))
					{
						if(comPortGet((uint8_t *)USB_data))globalMsgHandler((uint8_t *)USB_data);
					}
					else if (timeOut()) timeoutInc++; 
					
					if(timeoutInc > 100)
					{
						flashAdcInfo(i);
						while(dataInBuf(&bufTxD1));
						timeoutInc = 0;
					}
				
				}
				timeoutInc = 0;
				daqAlloc.standAlone.recInfoAck = 0;
				
#endif				
				//loop until all data has been read
				while(flash.curAddr < flash.finAddr)
				{
					
					//parse relevant data from the heap and increment the CurMemAddress
				//	cli();
					flash.curAddr = flashGetData(flash.curAddr,i,&adcBulkPacket.data);
				//	sei();
					
					//send packet
					adcBulkDataSend(i,&adcBulkPacket);
					while(dataInBuf(&bufTxD1));
					asm("nop");
#ifndef spoof
					while(daqAlloc.standAlone.recDataAck == 0)
					{
						if (dataInBuf(&bufRxD1))
						{
							if(comPortGet((uint8_t *)USB_data))globalMsgHandler((uint8_t *)USB_data);
						}
						//else if (timeOut())timeoutInc++;
						
						/*						
						if(timeoutInc >100)
						{
							adcBulkDataSend(i,&adcBulkPacket);
							while(dataInBuf(&bufTxD1));
							timeoutInc = 0;
						}
						*/
					}
					timeoutInc = 0;
					daqAlloc.standAlone.recDataAck = 0;
					
#endif					
				}//end of current channel bulk transfers
			}//end of flash reads and bulk transfers
			daqAlloc.standAlone.aqState = AQ_END_STATE;
			
			
			break;
			case AQ_END_STATE:
			
				asm("nop");
				sendEndOfProgram();
				while(daqAlloc.standAlone.recEOPACK == 0)
				{
					if (dataInBuf(&bufRxD1))
					{
						if(comPortGet((uint8_t *)USB_data))globalMsgHandler((uint8_t *)USB_data);
					}
					else if (timeOut())
					{
						sendEndOfProgram();
					}
				}
				while(1)
				{
					if (dataInBuf(&bufRxD1))
					{
						if(comPortGet((uint8_t *)USB_data))globalMsgHandler((uint8_t *)USB_data);
					}
					
				}
			
			break;
			
			
			
				
		}
	
	}
}

ISR(BADISR_vect)
{
	asm("nop");
}


